﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading;
using Microsoft.WindowsAzure.StorageClientExtensions;

namespace PartitionedCloudQueue.UnitTests
{
    [TestClass]
    public class NestedAsyncHelperTests
    {
        private class AsyncTestHelper
        {
            private int TestCall(int arg)
            {
                System.Threading.Thread.Sleep(100);
                return arg * 2;
            }

            private delegate int TestCallDelegate(int arg);                       

            public IAsyncResult BeginTest(int param, AsyncCallback callback, object state)
            {
                TestCallDelegate nested = new TestCallDelegate(TestCall);
                NestedAsyncHelper wrapper = NestedAsyncHelper.WrapBeginParameters(callback, state, nested);

                return wrapper.WrapAsyncResult(nested.BeginInvoke(param, NestedAsyncHelper.Callback, wrapper));
            }

            public int EndTest(IAsyncResult asyncResult)
            {                
                TestCallDelegate res = (TestCallDelegate)NestedAsyncHelper.GetExtraState(asyncResult);   
                return res.EndInvoke(NestedAsyncHelper.UnwrapAsyncResult(asyncResult));                
            }
        }

        [TestMethod]
        public void TestAsyncCallWithoutCallback()
        {
            AsyncTestHelper helper = new AsyncTestHelper();
            IAsyncResult res = helper.BeginTest(5, null, null);
            res.AsyncWaitHandle.WaitOne();

            Assert.AreEqual(10, helper.EndTest(res));
        }

        [TestMethod]
        public void TestAsyncCallWithCallback()
        {
            int result=0;

            ManualResetEvent evt = new ManualResetEvent(false);
            AsyncTestHelper helper = new AsyncTestHelper();
            IAsyncResult ar = helper.BeginTest(5, (asyncResult)=>
                {
                    result = helper.EndTest(asyncResult);
                    evt.Set();
                },
                helper);

            ar.AsyncWaitHandle.WaitOne();
            evt.WaitOne();

            Assert.AreEqual(10,result);
        }
    }
}
